www.gusucode.com > VC 套接字异步示例 > VC 套接字异步示例/gusucode/SockServerDlg.cpp

    // SockServerDlg.cpp : implementation file
// Download by http://www.NewXing.com

#include "stdafx.h"
#include "SockServer.h"
#include "SockServerDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSockServerDlg dialog

CSockServerDlg::CSockServerDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CSockServerDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CSockServerDlg)
	m_portServer = 1010;
	m_status = _T("");
	m_receiveData = _T("");
	m_commandToSend = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CSockServerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSockServerDlg)
	DDX_Control(pDX, IDC_LIST_CLIENT, m_lClient);
	DDX_Control(pDX, IDC_BUTTON_SEND, m_bSend);
	DDX_Control(pDX, IDC_STOPSERVER, m_stopServer);
	DDX_Control(pDX, IDC_STARTUP, m_startUp);
	DDX_Text(pDX, IDC_PORT_SERVER, m_portServer);
	DDX_Text(pDX, IDC_STATUS, m_status);
	DDX_Text(pDX, IDC_RECEIVEDATA, m_receiveData);
	DDX_Text(pDX, IDC_COMMANDTOSEND, m_commandToSend);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CSockServerDlg, CDialog)
	//{{AFX_MSG_MAP(CSockServerDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_STARTUP, OnStartup)
	ON_BN_CLICKED(IDC_STOPSERVER, OnStopserver)
	ON_MESSAGE(WM_SERVER_ACCEPT,OnServerAccept)
	ON_MESSAGE(WM_SERVER_READ,OnServerRead)
	ON_BN_CLICKED(IDC_BUTTON_SEND, OnButtonSend)
	ON_BN_CLICKED(IDC_BUTTON_CLEAN, OnButtonClean)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSockServerDlg message handlers

BOOL CSockServerDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	for (int i=0;i<MAXCLIENTNUM;i++)
	{
		sClient[i]=INVALID_SOCKET;
	}
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CSockServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CSockServerDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSockServerDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CSockServerDlg::OnStartup() 
{
	UpdateData(TRUE);
	// TODO: Add your control notification handler code here
	WORD wVersionRequested;
	WSADATA wsaData;
	unsigned long ul=1;
	int err,retal;
	wVersionRequested = MAKEWORD(1,1);
	err = WSAStartup(wVersionRequested, &wsaData );
	if ( err != 0 ) 
	{
		return;
	}	
	if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1)
	{
		WSACleanup( );
		return;
	}
	sockSrv=socket(AF_INET,SOCK_STREAM,0);	
	retal=WSAAsyncSelect(sockSrv, m_hWnd, WM_SERVER_ACCEPT, FD_ACCEPT);
	if (SOCKET_ERROR==retal)
	{
		m_status="设置异步模式失败!";
		UpdateData(FALSE);
		closesocket(sockSrv);
		WSACleanup();
		return;
	}
	addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
	addrSrv.sin_family=AF_INET;
	addrSrv.sin_port=htons(m_portServer);
	retal=bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
	if (SOCKET_ERROR==retal)
	{
		m_status="绑定失败!";
		UpdateData(FALSE);
		closesocket(sockSrv);
		WSACleanup();
		return;
	}
	//::WSAAsyncSelect(sockSrv,m_hWnd,WM_SOCKET,FD_ACCEPT|FD_CLOSE);
	retal=listen(sockSrv,MAXCLIENTNUM);
	if(SOCKET_ERROR==retal)
	{
		m_status="监听失败!";
		closesocket(sockSrv);
		WSACleanup();
		return;
	}
	m_startUp.EnableWindow(FALSE);
	m_status="start server sucess!!";
	m_status= m_status+"\r\n";
    m_status=m_status+"运行中等待服务请求.......\n";
	UpdateData(FALSE);
	m_stopServer.EnableWindow(TRUE);
}

LRESULT CSockServerDlg::OnServerAccept(WPARAM wParam, LPARAM lParam)
{
	int nLength = sizeof(SOCKADDR);
/*	int i;*/
	if (WSAGETSELECTEVENT(lParam) == FD_ACCEPT)
	{
		for(i=0;(i<MAXCLIENTNUM)&&(sClient[i]!=INVALID_SOCKET);i++) ;
		if(i==MAXCLIENTNUM)      
			return 0;
		sClient[i] = accept(sockSrv, (LPSOCKADDR)&addrClient, (LPINT)&nLength);
		uinfo[i].userip=inet_ntoa(addrClient.sin_addr);
		WSAAsyncSelect(sClient[i],m_hWnd,WM_SERVER_READ,FD_READ|FD_CLOSE);
		CTime t=CTime::GetCurrentTime();
		CString strTime="(%y-%m-%d %H:%M:%S)";
		strTime=t.Format(strTime);
		m_status=m_status+uinfo[i].userip+"连接服务器,时间:"+strTime+"\n";
		m_lClient.AddString(uinfo[i].userip);
		UpdateData(FALSE);		
	}
	return 0;
}

void CSockServerDlg::OnStopserver() 
{
	// TODO: Add your control notification handler code here
	m_startUp.EnableWindow(TRUE);
	m_stopServer.EnableWindow(FALSE);
	closesocket(sockSrv);
/*	int i;*/
	for(i=0;i<MAXCLIENTNUM;i++)
	    closesocket(sClient[i]);
	WSACleanup(); 
	m_status="stop server!";
	UpdateData(FALSE);
}

LRESULT CSockServerDlg::OnServerRead(WPARAM wParam, LPARAM lParam)
{
	if (WSAGETSELECTEVENT(lParam) == FD_READ)  //网络数据到达事件
	{ 
	  CString s;
/*      int i;*/
	  for(i=0;(i<MAXCLIENTNUM)&&(sClient[i]!=wParam);i++);
	  if(i==MAXCLIENTNUM) return 0;
      int BRead;
	  char szText[1024]={0};
	  BRead=recv(sClient[i], (char*)&szText,1024, 0);
      if (BRead == SOCKET_ERROR)
	      MessageBox("接收到一个错误信息!");
	  CTime t=CTime::GetCurrentTime();
	  CString strTime="(%y-%m-%d %H:%M:%S)";
	  strTime=t.Format(strTime);
	  m_receiveData=m_receiveData+strTime+"用户由ip"+uinfo[i].userip+"发送:"+CString(szText)+"\r\n";
	  UpdateData(FALSE);
 	}
    if (WSAGETSELECTEVENT(lParam) == FD_CLOSE)   //客户端断开事件
	{   
		CTime t=CTime::GetCurrentTime();
		CString strTime="(%y-%m-%d %H:%M:%S)";
		strTime=t.Format(strTime);

		for(i=0;(i<20)&&(sClient[i]!=wParam);i++) ;
	    closesocket(sClient[i]);
	    sClient[i] = INVALID_SOCKET;
	    //sendinfo closeinfo,closeinfo1;
		m_status=m_status+strTime+"用户"+uinfo[i].username+"由ip"+uinfo[i].userip+"退出服务器";
		m_lClient.DeleteString(m_lClient.FindString(1,uinfo[i].userip));
	    uinfo[i].userip="";
        uinfo[i].username="";

		UpdateData(FALSE);				
	}
	    CEdit *pEdit;
		pEdit=(CEdit *)GetDlgItem(IDC_STATUS);
		int i=pEdit->GetLineCount();
		pEdit->LineScroll(i,0);
	return 0L;
}

void CSockServerDlg::OnButtonSend() 
{
	// TODO: Add your control notification handler code here
	UpdateData(TRUE);
	CString selectClientIP;
	m_lClient.GetText(m_lClient.GetCurSel(),selectClientIP);
	UpdateData(FALSE);
	char strText[1024]={0};
	strcpy(strText,m_commandToSend);
	send(sClient[i],(char*)&strText,strlen(strText),0);
	m_status=m_status+"正在给用户"+selectClientIP+"发送指令\r\n";
	UpdateData(FALSE);	
}

void CSockServerDlg::OnButtonClean() 
{
	// TODO: Add your control notification handler code here
	m_receiveData="";
	UpdateData(FALSE);
}